#include <iostream>
#include "InitAddr.hpp"
#include <string>
#include <memory>
#include <jsoncpp/json/json.h>
#include "Socket.hpp"

using namespace SocketModule;

// 约定好每个字段的含义，本质上就是约定好协议
// 如何做到序列化和反序列化？
// 1、自己写
// 2、使用现成的方案--->json->jsoncpp

// 我们对于完整性应该怎样处理呢？
// read只能保证数据如果有就把数据读上来。数据完整性只能由程序员自己控制
class Request
{
public:
    Request() {}

    Request(int x, int y, char oppr)
        : _x(x), _y(y), _oppr(oppr)
    {
    }

    std::string Serialize()
    {
        // 后缀表达式转中缀表达式，就是序列化的过程
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oppr"] = _oppr;

        //此处还可以采用stypedwriter来进行以类似于结构体的方式进行输出的方式
        Json::FastWriter writer;
        //
        std::string s = writer.write(root);
        return s;
    }
    //

    bool UnSerialize(std::string &in)
    {
        // 逆波兰表达式求值就是反序列化得出结构的过程
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oppr = root["oppr"].asInt();
        }
        return ok;
    }

private:
    int _x;
    int _y;
    char _oppr;
};

class Response
{
public:
    Response()
    {
    }

    std::string &Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }

    bool UnSerialize(std::string &s)
    {
        Json::Value root;
        Json::Reader reader;

        bool ok = reader.parse(s, root);
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return ok;
    }

private:
    int _result;
    int _code;
};

const std::string sep = "\r\n";

class Protocol
{
public:
    Protocol() {}

    void GetRequest(std::unique_ptr<Socket> &sock, InitAddr &client)
    {
        //这里的缓冲区实际上时缓冲区队列，每次都将没能一次性读完的数据入队列
        //等待队列满了的时候再清队列
        std::string inbuffer_queue;
        while (1)
        {
            int n = sock->Recv(&inbuffer_queue);
            if (n > 0)
            {
                std::string json_package;
                if (!Decode(inbuffer_queue, &json_package))
                {
                    continue;
                }
                Request req;
                if(!req.UnSerialize(json_package))
                {
                    continue;
                }
                //我一定得到了一个内部属性已经被设置了的req了
            }
            else
                break;
        }
    }

    std::string Encode(const std::string jsonstr)
    {
        // 应用层报头封装——封装的是有效载荷的长度
        std::string len = std::to_string(jsonstr.size());
        return len + sep + jsonstr + sep;
    }

    bool Decode(std::string &buffer, std::string *package)
    {
        //添加报头
        int pos = buffer.find(sep);
        if (pos == std::string::npos)
            return false;
        std::string package_len_string = buffer.substr(0, pos);
        int package_len_int = std::stoi(package_len_string);
        int target_len = sep.size() * 2 + package_len_int + package_len_string.size();
        if (target_len < buffer.size())
        {
            return false;
        }
        *package = buffer.substr(pos + sep.size(), target_len);
        buffer.erase(0, target_len);
        return true;
    }

    std::string BuildRequestString(int x, int y, char oper)
    {
        Request req(x, y, oper);

        std::string json_string = req.Serialize();

        return Encode(json_string);
    }

private:
    Request _req;
    Response _resp;
};
